#include "DriverController.h"
#include "mainWindow.h"
#include "control/DataControl.h"

#include <QTimer>
#include <QMimeData>
#include <QApplication>

// === PortDeviceModel 实现 ===

static inline quintptr makeInternalId(PortPair* pair, int typeFlag)
{
    // Assume pointer alignment >= 4, reserve low 2 bits for type flag
    return (reinterpret_cast<quintptr>(pair) & ~quintptr(3)) | (quintptr(typeFlag) & 3);
}

static inline PortPair* getPairFromId(quintptr id)
{
    return reinterpret_cast<PortPair*>(id & ~quintptr(3));
}

static inline int getTypeFromId(quintptr id)
{
    return int(id & 3);
}

static inline int findPairRow(const QVector<PortPair*>& pairs, const PortPair* target)
{
    for (int i = 0; i < pairs.size(); ++i) {
        if (pairs[i] == target) return i;
    }
    return -1;
}

/************************* PortDeviceModel **************************/

QVector<PortPair*> PortDeviceModel::sm_portPairs;
QSet<QString> PortDeviceModel::sm_endpointPorts;
QString PortDeviceModel::sm_inputPortName;

PortDeviceModel::PortDeviceModel(QObject *parent)
{
}

PortDeviceModel::~PortDeviceModel()
{
    clearData();
}

QModelIndex PortDeviceModel::index(int row, int column, const QModelIndex &parent) const
{
    if (row < 0 || column < 0) {
        return QModelIndex();
    }

    // 顶层：总线设备列表
    if (!parent.isValid()) {
        if (row >= sm_portPairs.size() || column >= 4) {
            return QModelIndex();
        }
        // internalId: PortPair* | 0 => Bus
        return createIndex(row, column, makeInternalId(sm_portPairs[row], 0));
    }

    // 次级：每个总线设备下的两个固定端口
    // 解析父节点，获取其对应的 PortPair 行索引
    const quintptr pid = parent.internalId();
    const PortPair* pair = getPairFromId(pid);
    const int typeFlag = getTypeFromId(pid);
    if (typeFlag != 0 || !pair) {
        // 父节点不是Bus，则不再有子节点
        return QModelIndex();
    }
    int pairRow = findPairRow(sm_portPairs, pair);
    if (row >= 2 || column >= 4 || pairRow < 0) {
        return QModelIndex();
    }
    // internalId: PortPair* | childType; 1 => PortA, 2 => PortB
    const int childType = (row == 0) ? 1 : 2;
    return createIndex(row, column, makeInternalId(sm_portPairs[pairRow], childType));
}

QModelIndex PortDeviceModel::parent(const QModelIndex &child) const
{
    if (!child.isValid()) {
        return QModelIndex();
    }
    const quintptr cid = child.internalId();
    PortPair* pair = getPairFromId(cid);
    const int typeFlag = getTypeFromId(cid);
    // 顶层（Bus）无父节点；端口节点的父节点为对应的Bus
    if (typeFlag == 0) {
        return QModelIndex();
    }
    int pairRow = findPairRow(sm_portPairs, pair);
    if (pairRow < 0) {
        return QModelIndex();
    }
    return createIndex(pairRow, 0, makeInternalId(sm_portPairs[pairRow], 0));
}

int PortDeviceModel::rowCount(const QModelIndex &parent) const
{
    // 顶层：总线设备数量
    if (!parent.isValid()) {
        return sm_portPairs.size();
    }

    // 次级：每个总线设备下固定两个端口
    const quintptr pid = parent.internalId();
    /// 低2位为类型
    const int typeFlag = getTypeFromId(pid);
    if (typeFlag == 0) {
        // 为bus设备
        return 2;
    }
    return 0;
}

int PortDeviceModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    // 多列显示：名称/类型/状态/端口对
    return 4;
}

static QStringList splitPairNames(const QString &pairId)
{
    // 约定格式：CNCA{n}-CNCB{n}
    const QStringList parts = pairId.split('-', QString::SkipEmptyParts);
    if (parts.size() == 2) return parts;
    return {};
}

static QString deviceTypeToString(DeviceType t)
{
    switch (t) {
    case DeviceType::BusDevice:      return QString("总线");
    case DeviceType::VirtualPort:    return QString("虚拟端口");
    case DeviceType::VirtualPortCst: return QString("虚拟端口");
    case DeviceType::Unknown:
    default:                         return QString("未知");
    }
}

static QString deviceStateToString(DeviceState s)
{
    switch (s) {
    case DeviceState::Active:    return QString("已启动");
    case DeviceState::Inactive:  return QString("未启动");
    case DeviceState::Disabled:  return QString("已禁用");
    case DeviceState::Removed:   return QString("已移除");
    case DeviceState::Unknown:
    default:                     return QString("未知");
    }
}

QVariant PortDeviceModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }

    // 自定义角色：是否已加入 endpoints（用于状态灯）
    if (role == Qt::UserRole + 1) {
        const quintptr id = index.internalId();
        PortPair* pair = getPairFromId(id);
        const int typeFlag = getTypeFromId(id);
        if (!pair) {
            return QVariant();
        }
        if (typeFlag == 0) {
            // Bus 行不显示状态灯
            return false;
        }
        const bool isA = (typeFlag == 1);
        const DeviceInfo* port = isA ? pair->portA() : pair->portB();
        if (!port) {
            return false;
        }
        return sm_inputPortName == port->portName ?
                   INPUT_PORT : isEndPoint(port->portName) ? ENDPOINT_PORT : ROUTINE_PORT;
    }

    if (role != Qt::DisplayRole) {
        return QVariant();
    }

    const quintptr id = index.internalId();
    PortPair* pair = getPairFromId(id);
    const int typeFlag = getTypeFromId(id);
    if (!pair) {
        return QVariant();
    }

    if (typeFlag == 0) {
        // 顶层：总线设备
        const DeviceInfo* bus = pair->busDevice();
        if (!bus) return QVariant();
        switch (index.column()) {
        case 0: return bus->friendlyName;                // 名称
        case 1: return deviceTypeToString(bus->type);    // 类型
        case 2: return deviceStateToString(bus->state);  // 状态
        case 3: return bus->portPair.toUpper();          // 端口对
        default: return QVariant();
        }
    }

    // 次级：两个固定端口
    const bool isA = (typeFlag == 1);
    const DeviceInfo* port = isA ? pair->portA() : pair->portB();
    switch (index.column()) {
    case 0: {
        if (port) {
            return port->portName; // 名称
        }
        return QVariant();
    }
    case 1: {
        // 类型
        return port ? deviceTypeToString(port->type) : QString("虚拟端口");
    }
    case 2: {
        // 状态
        return port ? deviceStateToString(port->state) : QString("未连接");
    }
    case 3: {
        // 端口数据类型
        return sm_inputPortName == port->portName ?
            "控制串口" : isEndPoint(port->portName) ? "Split端口" : "自由端口";
    }
    default:
        return QVariant();
    }
}

Qt::ItemFlags PortDeviceModel::flags(const QModelIndex &index) const
{
    int itemType = getTypeFromId(index.internalId());
    const PortPair* pair = getPairInfo(index);
    if (itemType == 0) {
        return QAbstractItemModel::flags(index);
    } else {
        QString portName;
        if (itemType == 1) {
            portName = pair->portA()->portName;
        } else if (itemType == 2) {
            portName = pair->portB()->portName;
        }
        Qt::ItemFlags flags = Qt::NoItemFlags;
        if (!isEndPoint(portName)) {
            flags |= Qt::ItemIsDragEnabled;
        }
        return QAbstractItemModel::flags(index) | flags;
    }
}

QStringList PortDeviceModel::mimeTypes() const
{
    return {MIME_TYPE};
}

QMimeData *PortDeviceModel::mimeData(const QModelIndexList &indexes) const
{
    auto idx = indexes.first();
    QMimeData *data = new QMimeData();
    const PortPair *pair = getPairInfo(idx);
    if (getTypeFromId(idx.internalId()) == 1) {
        data->setData(MIME_TYPE, pair->portA()->portName.toLocal8Bit());
    } else if (getTypeFromId(idx.internalId()) == 2) {
        data->setData(MIME_TYPE, pair->portB()->portName.toLocal8Bit());
    }
    return data;
    return nullptr;
}

const PortPair *PortDeviceModel::getPairInfo(QModelIndex idx)
{
    if (!idx.isValid()) {
        return nullptr;
    }

    quintptr data = idx.internalId();
    int typeFlag = getTypeFromId(data);
    if (typeFlag > 2 || typeFlag < 0) {
        return nullptr;
    }
    return getPairFromId(data);
}

const bool PortDeviceModel::isEndPoint(const QString &portName)
{
    return sm_endpointPorts.contains(portName);
}

const PortPair *PortDeviceModel::getPairFromPortName(const QString &portName)
{
    for (const PortPair* pair : sm_portPairs) {
        if (pair->portA()->portName == portName || pair->portB()->portName == portName)
            return pair;
    }
    return nullptr;
}

QVariant PortDeviceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation != Qt::Horizontal || role != Qt::DisplayRole) {
        return QVariant();
    }
    switch (section) {
    case 0: return QString("名称");
    case 1: return QString("类型");
    case 2: return QString("状态");
    case 3: return QString("分流类型");
    default: return QVariant();
    }
}

// 内存管理实现
void PortDeviceModel::takeOwnership(QVector<PortPair*>&& portPairs)
{
    // 通知视图即将重置数据
    beginResetModel();
    // 清理现有数据
    clearData();
    // 接管新数据的所有权
    sm_portPairs = std::move(portPairs);
    // 通知视图数据重置完成
    endResetModel();
}

void PortDeviceModel::clearData()
{
    // 释放所有 PortPair 对象的内存
    for (PortPair* pair : sm_portPairs) {
        delete pair;
    }
    sm_portPairs.clear();
}

void PortDeviceModel::setInputSelected(const QString &portName)
{
    sm_inputPortName = portName;
    if (!sm_inputPortName.isEmpty()) {
        for (int i = 0; i < sm_portPairs.size(); ++i) {
            PortPair *pair = sm_portPairs.at(i);
            if (!pair) continue;
            const bool matchA = (pair->portA() && pair->portA()->portName == portName);
            const bool matchB = (pair->portB() && pair->portB()->portName == portName);
            if (matchA || matchB) {
                QModelIndex parentIdx = createIndex(i, 0, makeInternalId(pair, 0));
                const int childRow = matchA ? 0 : 1;
                QModelIndex childCol2 = index(childRow, 2, parentIdx);
                emit dataChanged(childCol2, childCol2, {Qt::UserRole + 1});
            }
        }
    } else {
        emit layoutChanged();
    }
}

void PortDeviceModel::setEndpointSelected(const QString &portName, bool selected)
{
    const bool existed = sm_endpointPorts.contains(portName);
    if (selected) {
        if (!existed) sm_endpointPorts.insert(portName);
    } else {
        if (existed) sm_endpointPorts.remove(portName);
    }

    // 找到匹配的端口行并通知视图刷新第三列（状态灯）
    for (int i = 0; i < sm_portPairs.size(); ++i) {
        PortPair* pair = sm_portPairs[i];
        if (!pair) continue;
        const bool matchA = (pair->portA() && pair->portA()->portName == portName);
        const bool matchB = (pair->portB() && pair->portB()->portName == portName);
        if (matchA || matchB) {
            QModelIndex parentIdx = createIndex(i, 0, makeInternalId(pair, 0));
            const int childRow = matchA ? 0 : 1;
            QModelIndex childCol2 = index(childRow, 2, parentIdx);
            emit dataChanged(childCol2, childCol2, {Qt::UserRole + 1});
        }
    }
}

void PortDeviceModel::deviceFoundHandle(const DeviceInfo &info)
{
    if (!info.isValid) {
        return;
    }

    if (info.type == DeviceType::BusDevice) {
        const int row = sm_portPairs.size();
        beginInsertRows(QModelIndex(), row, row);
        sm_portPairs.append(new PortPair(new DeviceInfo(info)));
        endInsertRows();
        qDebug() << "Probes Bus Device" << info.portPair;
    } else if (info.type == DeviceType::VirtualPort || info.type == DeviceType::VirtualPortCst) {
        bool found = false;
        for (int i = 0; i < sm_portPairs.size(); ++i) {
            PortPair* pair = sm_portPairs[i];
            if (pair->busDevice() && pair->busDevice()->portPair == info.portPair) {
                const bool fillB = (pair->portA() != nullptr);
                if (fillB) {
                    pair->setPortB(new DeviceInfo(info));
                } else {
                    pair->setPortA(new DeviceInfo(info));
                }
                // 通知视图更新对应的子节点
                QModelIndex parentIdx = createIndex(i, 0, makeInternalId(pair, 0));
                const int childRow = fillB ? 1 : 0;
                QModelIndex childIdx = index(childRow, 0, parentIdx);
                emit dataChanged(childIdx, childIdx, {});
                // 同步刷新父节点（分支/连线区域依赖父项重绘）
                emit dataChanged(parentIdx, parentIdx, {});
                found = true;
                break;
            }
        }
        if (!found) {
            qDebug() << "Warning:" << "Probes New Port Device" << info.portName << "But Not Found New Device Matching Pair";
        }
    }
}

void PortDeviceModel::deviceRemovedHandle(const DeviceInfo &info)
{
    if (!info.isValid) {
        return;
    }

    if (info.type == DeviceType::BusDevice) {
        // 移除对应的 PortPair
        for (int i = sm_portPairs.size() - 1; i >= 0; --i) {
            PortPair* pair = sm_portPairs[i];
            if (pair->busDevice() && 
                pair->busDevice()->hardwareId == info.hardwareId &&
                pair->busDevice()->friendlyName == info.friendlyName) {
                beginRemoveRows(QModelIndex(), i, i);
                sm_portPairs.removeAt(i);
                delete pair;
                endRemoveRows();
                break;
            }
        }
    } else if (info.type == DeviceType::VirtualPort || info.type == DeviceType::VirtualPortCst) {
        // 移除对应的端口设备
        for (int i = 0; i < sm_portPairs.size(); ++i) {
            PortPair* pair = sm_portPairs[i];
            if (pair->busDevice() && pair->busDevice()->portPair == info.portPair) {
                int childRow = -1;
                if (pair->portA() && 
                    pair->portA()->portName == info.portName &&
                    pair->portA()->portPair == info.portPair) {
                    delete pair->portA();
                    pair->setPortA(nullptr);
                    childRow = 0;
                } else if (pair->portB() && 
                           pair->portB()->portName == info.portName &&
                           pair->portB()->portPair == info.portPair) {
                    delete pair->portB();
                    pair->setPortB(nullptr);
                    childRow = 1;
                }
                if (childRow != -1) {
                    QModelIndex parentIdx = createIndex(i, 0, makeInternalId(pair, 0));
                    QModelIndex childIdx = index(childRow, 0, parentIdx);
                    emit dataChanged(childIdx, childIdx, {});
                    // 同步刷新父节点（分支/连线区域依赖父项重绘）
                    emit dataChanged(parentIdx, parentIdx, {});
                }
                break;
            }
        }
    }

    qDebug() << "Removed Device" << info.portName;
}

/************************* DriverController **************************/

DriverController::DriverController(QObject *parent)
    : QObject{parent}
    , m_driverManager(new DriverManager(this))
    , m_portDeviceModel(new PortDeviceModel(this))
{
}

DriverController::~DriverController()
{
}

void DriverController::initialize()
{
    connect(m_driverManager, &DriverManager::initializationCompleted, this, &DriverController::buildDeviceTree);
    connect(m_driverManager, &DriverManager::deviceFound, m_portDeviceModel, &PortDeviceModel::deviceFoundHandle);
    connect(m_driverManager, &DriverManager::deviceRemoved, m_portDeviceModel, &PortDeviceModel::deviceRemovedHandle);
    connect(this, &DriverController::createPortPairSignal, m_driverManager, &DriverManager::createPortPair);
    connect(this, &DriverController::removedPortPairSignal, m_driverManager, &DriverManager::removePortPair);

    m_driverManager->initialize();
}

void DriverController::refreshVirtualPortList()
{
    m_driverManager->refreshDeviceList();
}

void DriverController::buildDeviceTree()
{
    int busNum = 0, portNum = 0;
    // 创建临时的 PortPair 容器，由 DriverController 分配内存
    QVector<PortPair*> portPairs;
    QMap<QString, PortPair*> busDeviceMap; // 用于快速查找总线设备对应的 PortPair

    const QList<DeviceInfo> devList = m_driverManager->getDeviceList();
    
    // 第一遍遍历：处理总线设备，创建 PortPair 对象
    for (const DeviceInfo& info : devList) {
        if (!info.isValid) {
            continue;
        }
        if (info.type == DeviceType::BusDevice) {
            // 为总线设备创建 PortPair 对象
            PortPair* pair = new PortPair(new DeviceInfo(info));
            portPairs.append(pair);
            busDeviceMap.insert(info.portPair, pair); // 使用 portPair 作为键进行映射
            busNum++;
        }
    }
    
    // 第二遍遍历：处理虚拟端口设备，关联到对应的 PortPair
    for (const DeviceInfo& info : devList) {
        if (!info.isValid) {
            continue;
        }
        if (info.type == DeviceType::VirtualPort || info.type == DeviceType::VirtualPortCst) {
            // 查找对应的 PortPair
            PortPair* pair = busDeviceMap.value(info.portPair, nullptr);
            if (pair) {
                if (pair->portA()) {
                    pair->setPortB(new DeviceInfo(info));
                } else {
                    pair->setPortA(new DeviceInfo(info));
                }
                portNum++;
            }
        }
    }

    ADD_LOG(QString::asprintf(">>> Build Tree Finished, %d Bus %d Port <<<", busNum, portNum));

    // 将所有权转移给 PortDeviceModel
    m_portDeviceModel->takeOwnership(std::move(portPairs));
}

void DriverController::setInputSelected(const QString &portName)
{
    if (!m_portDeviceModel) return;
    m_portDeviceModel->setInputSelected(portName);
}

void DriverController::setEndpointSelected(const QString &portName, bool selected)
{
    if (!m_portDeviceModel) return;
    m_portDeviceModel->setEndpointSelected(portName, selected);
}
